//
//  JCStringExtension.swift
//  JCPublicKit
//
//  Created by JasonLee on 2020/5/13.
//

import Foundation

extension String {
    subscript(start: Int, end: Int) -> String {
        get {
            guard end > start else { return "" }
            guard start >= 0, start <= count - 1 else { return "" }
            let theStartIndex = index(startIndex, offsetBy: start)
            var tempEnd = end
            if end > count {
                tempEnd = count
            }
            let theEndIndex = index(startIndex, offsetBy: tempEnd)
            return String(self[theStartIndex..<theEndIndex])
        }
        set {
            // 当 传递了错误的区间时，不操作
            guard end > start else { return }
            // 当 区间起始下标 大于 字符串末位下标 时，直接拼接字符串
            guard start < count else {
                self = "\(self)\(newValue)"
                return
            }
            // 当 区间末位下标 大于 字符串末位下标 时，替换至字符串末位下标，然后拼接剩余字符
            guard end < count else {
                
                return
            }
            let theFirstEndIndex = index(startIndex, offsetBy: start)
            let theSecondStartIndex = index(startIndex, offsetBy: end)
            let startString = self[..<theFirstEndIndex]
            let endString = self[theSecondStartIndex..<endIndex]
            self = "\(startString)\(newValue)\(endString)"
        }
    }
    func jc_substring(from start: Int, to end: Int) -> String {
        return String(self[index(startIndex, offsetBy: start)..<index(startIndex, offsetBy: end)])
    }
    
    var jc_url: URL? {
        URL(string: self)
    }
    var jc_isAlphaNumeric: Bool {
        let inverseSet = NSCharacterSet(charactersIn: "0123456789").inverted
        let components = self.components(separatedBy: inverseSet)
        let filtered = components.joined(separator: "")
        return self == filtered
    }
    var jc_isAlphabetic: Bool {
        let hasLetters = rangeOfCharacter(from: .letters, options: .numeric, range: nil) != nil
        let hasNumbers = rangeOfCharacter(from: .decimalDigits, options: .literal, range: nil) != nil
        return hasLetters && !hasNumbers
    }
    var jc_isEmail: Bool {
        // http://emailregex.com/
        let regex = "^(?:[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\p{L}0-9](?:[a-z0-9-]*[\\p{L}0-9])?\\.)+[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[\\p{L}0-9-]*[\\p{L}0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$"
        return range(of: regex, options: .regularExpression, range: nil, locale: nil) != nil
    }
    
    @discardableResult
    mutating func jc_urlDecode() -> String {
        if let decoded = removingPercentEncoding {
            self = decoded
        }
        return self
    }
    @discardableResult
    mutating func jc_urlEncode() -> String {
        if let encoded = addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) {
            self = encoded
        }
        return self
    }
    
    var jc_reversed: String {
        var string = self
        string.jc_reverse()
        return string
    }
    mutating func jc_reverse() {
        let mappedCharacters = self.map{ return $0 }
        let reversed = mappedCharacters.reversed()
        self = String(reversed)
    }
    
    func jc_split(_ separator: Character) -> [String] {
        return self.split(separator: separator).map(String.init)
    }
    func jc_split(from start: Int, to end: Int) -> String {
        let startIndex = self.index(self.startIndex, offsetBy: start)
        let endIndex = self.index(self.startIndex, offsetBy: end)
        return String(self[startIndex..<endIndex])
    }
}

extension String {
    static func jc_random(length: Int = 1) -> String {
        guard length > 0 else { return "" }
        let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString = ""
        for _ in 1...length {
            randomString.append(base.randomElement()!)
        }
        return randomString
    }
    static func jc_string(date: Date, dateFormatter: DateFormatter) -> String {
        dateFormatter.string(from: date)
    }
    static func jc_string(date: Date, dateFormat: String) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = dateFormat
        return jc_string(date: date, dateFormatter: dateFormatter)
    }
    
    func jc_toArray() -> [String] {
        return self.map { String($0) }
    }
}
